﻿using System;
using System.Collections.Generic;

using RoughJs.Error;
using System.IO;
using System.Globalization;

namespace RoughJs.Ast
{
    /// <summary>
    /// 2010-01-5 ----- 2010-01-29
    /// 陈曦 1.0
    /// Microsoft Public License (Ms-PL)
    ///This license governs use of the accompanying software. If you use the software, you accept this license. If you do not accept the license, do not use the software.
    ///1. Definitions
    ///The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under U.S. copyright law.
    ///A "contribution" is the original software, or any additions or changes to the software.
    ///A "contributor" is any person that distributes its contribution under this license.
    ///"Licensed patents" are a contributor's patent claims that read directly on its contribution.
    ///2. Grant of Rights
    ///(A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create.
    ///(B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software.
    ///3. Conditions and Limitations
    ///(A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks.
    ///(B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically.
    ///(C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software.
    ///(D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license.
    ///(E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement. 
    /// </summary>
    public class Context
    {

        public const int VERSION_UNKNOWN = -1;


        public const int VERSION_DEFAULT = 0;

        public const int VERSION_1_0 = 100;


        public const int VERSION_1_1 = 110;


        public const int VERSION_1_2 = 120;


        public const int VERSION_1_3 = 130;


        public const int VERSION_1_4 = 140;


        public const int VERSION_1_5 = 150;


        public const int VERSION_1_6 = 160;

        public const int VERSION_1_7 = 170;



        public const int FEATURE_NON_ECMA_GET_YEAR = 1;


        public const int FEATURE_MEMBER_EXPR_AS_FUNCTION_NAME = 2;


        public const int FEATURE_RESERVED_KEYWORD_AS_IDENTIFIER = 3;


        public const int FEATURE_TO_STRING_AS_SOURCE = 4;


        public const int FEATURE_PARENT_PROTO_PROPERTIES = 5;


        public const int FEATURE_PARENT_PROTO_PROPRTIES = 5;


        public const int FEATURE_E4X = 6;


        public const int FEATURE_DYNAMIC_SCOPE = 7;


        public const int FEATURE_STRICT_VARS = 8;

        public const int FEATURE_STRICT_EVAL = 9;


        public const int FEATURE_LOCATION_INFORMATION_IN_ERROR = 10;


        public const int FEATURE_STRICT_MODE = 11;


        public const int FEATURE_WARNING_AS_ERROR = 12;

        public const int FEATURE_ENHANCED_JAVA_ACCESS = 13;


        public bool hasFeature(int featureIndex)
        {
            ContextFactory f = getFactory();
            return f.hasFeature(this, featureIndex);

        }
        /// <summary>
        /// 得到上下文工厂
        /// </summary>
        /// <returns></returns>
        public ContextFactory getFactory()
        {
            return factory;
        }
        private ContextFactory factory;

        public bool stringIsCompilableUnit(String source)
        {
            bool errorseen = false;
            CompilerEnvirons compilerEnv = new CompilerEnvirons();
            compilerEnv.initFromContext(this);
            compilerEnv.setGeneratingSource(false);
            Parser p = new Parser(compilerEnv, DefaultErrorReporter.instance);
            try
            {
                p.parse(source, null, 1);
            }
            catch
            {
                errorseen = true;
            }
            if (errorseen && p.eof())
                return false;
            else
                return true;
        }
        /// <summary>
        /// Get the current optimization level.
        /// </summary>
        /// <returns></returns>
        public int getOptimizationLevel()
        {
            return optimizationLevel;
        }

        public static EvaluatorException reportRuntimeError0(String messageId)
        {
            String msg = ScriptRuntime.getMessage0(messageId);
            return reportRuntimeError(msg);
        }


        /// <summary>
        /// 使用 Reporter 记录一个当前运行的错误
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        public static EvaluatorException reportRuntimeError(String message)
        {
            int[] linep = { 0 };
            String filename = getSourcePositionFromStack(linep);
            return Context.reportRuntimeError(message, filename, linep[0], null, 0);
        }


        /// <summary>
        ///  使用 Reporter 记录一个当前运行的错误
        /// </summary>
        /// <param name="message">报告的错误信息</param>
        /// <param name="sourceName">源文件名</param>
        /// <param name="lineno">行号</param>
        /// <param name="lineSource">所在行的源信息</param>
        /// <param name="lineOffset">lineOffset the offset into lineSource where problem was detected</param>
        /// <returns></returns>
        public static EvaluatorException reportRuntimeError(String message,
                                                            String sourceName,
                                                            int lineno,
                                                            String lineSource,
                                                            int lineOffset)
        {
            Context cx = getCurrentContext();
            if (cx != null)
            {
                return cx.getErrorReporter().
                                runtimeError(message, sourceName, lineno,
                                             lineSource, lineOffset);
            }
            else
            {
                throw new EvaluatorException(message, sourceName, lineno,
                                             lineSource, lineOffset);
            }
        }

        public static EvaluatorException reportRuntimeError1(String messageId,
                                                   Object arg1)
        {
            String msg = ScriptRuntime.getMessage1(messageId, arg1);
            return reportRuntimeError(msg);
        }

        public static EvaluatorException reportRuntimeError2(String messageId,
                                                      Object arg1, Object arg2)
        {
            String msg = ScriptRuntime.getMessage2(messageId, arg1, arg2);
            return reportRuntimeError(msg);
        }

        public static EvaluatorException reportRuntimeError3(String messageId,
                                                      Object arg1, Object arg2,
                                                      Object arg3)
        {
            String msg = ScriptRuntime.getMessage3(messageId, arg1, arg2, arg3);
            return reportRuntimeError(msg);
        }

        public static EvaluatorException reportRuntimeError4(String messageId,
                                                      Object arg1, Object arg2,
                                                      Object arg3, Object arg4)
        {
            String msg
                = ScriptRuntime.getMessage4(messageId, arg1, arg2, arg3, arg4);
            return reportRuntimeError(msg);
        }

        /// <summary>
        /// 得到当前运行错误的报到
        /// </summary>
        /// <returns></returns>
        public ErrorReporter getErrorReporter()
        {
            if (errorReporter == null)
            {
                return DefaultErrorReporter.instance;
            }
            return errorReporter;
        }

        /// <summary>
        /// 得到当前的上下文
        /// </summary>
        /// <returns></returns>
        public static Context getCurrentContext()
        {
            Object helper = VMBridge.instance.getThreadContextHelper();
            return VMBridge.instance.getContext(helper);
        }

        public static String getSourcePositionFromStack(int[] linep)
        {
            Context cx = getCurrentContext();
            if (cx == null)
                return null;
            if (cx.lastInterpreterFrame != null)
            {
                Evaluator evaluator = createInterpreter();
                if (evaluator != null)
                    return evaluator.getSourcePositionFromStack(cx, linep);
            }
            /**
             * A bit of a hack, but the only way to get filename and line
             * number from an enclosing frame.
             */
            //CharArrayWriter writer = new CharArrayWriter();
            //RuntimeException re = new RuntimeException();
            //re.printStackTrace(new PrintWriter(writer));
            //String s = writer.toString();
            //int open = -1;
            //int close = -1;
            //int colon = -1;
            //for (int i = 0; i < s.Length; i++)
            //{
            //    char c = s.ToCharArray()[i];
            //    if (c == ':')
            //        colon = i;
            //    else if (c == '(')
            //        open = i;
            //    else if (c == ')')
            //        close = i;
            //    else if (c == '\n' && open != -1 && close != -1 && colon != -1 &&
            //             open < colon && colon < close)
            //    {
            //        String fileStr = s.substring(open + 1, colon);
            //        if (!fileStr.endsWith(".java"))
            //        {
            //            String lineStr = s.substring(colon + 1, close);
            //            try
            //            {
            //                linep[0] = Integer.parseInt(lineStr);
            //                if (linep[0] < 0)
            //                {
            //                    linep[0] = 0;
            //                }
            //                return fileStr;
            //            }
            //            catch (Exception e)
            //            {
            //                // fall through
            //            }
            //        }
            //        open = close = colon = -1;
            //    }
            //}
            //TODO;这里暂时也不知道有什么用
            return null;
        }
        /**
     * Tell whether debug information is being generated.
     * @since 1.3
     */
        public bool isGeneratingDebug()
        {
            return generatingDebug;
        }
        public static bool isValidOptimizationLevel(int optimizationLevel)
        {
            return -1 <= optimizationLevel && optimizationLevel <= 9;
        }

        public static void checkOptimizationLevel(int optimizationLevel)
        {
            if (isValidOptimizationLevel(optimizationLevel))
            {
                return;
            }
            throw new Exception(
                "Optimization level outside [-1..9]: " + optimizationLevel);
        }


        public static Evaluator createInterpreter()
        {
            return new Interpreter();

        }

        /**
     * This is the list of names of objects forcing the creation of
     * function activation records.
     */
        public IList<String> activationNames;

        /**
    * Tell whether source information is being generated.
    * @since 1.3
    */
        public bool isGeneratingSource()
        {
            return generatingSource;
        }
        /// <summary>
        /// 得到当前的版本号
        /// </summary>
        /// <returns></returns>
        public int getLanguageVersion()
        {
            return version;
        }
        int version;

        public bool isGeneratingDebugChanged()
        {
            return generatingDebugChanged;
        }
        public static bool isValidLanguageVersion(int version)
        {
            switch (version)
            {
                case VERSION_DEFAULT:
                case VERSION_1_0:
                case VERSION_1_1:
                case VERSION_1_2:
                case VERSION_1_3:
                case VERSION_1_4:
                case VERSION_1_5:
                case VERSION_1_6:
                case VERSION_1_7:
                    return true;
            }
            return false;
        }
        public static void checkLanguageVersion(int version)
        {
            if (isValidLanguageVersion(version))
            {
                return;
            }
            throw new Exception("Bad language version: " + version);
        }

        public bool isVersionECMA1()
        {
            return version == VERSION_DEFAULT || version >= VERSION_1_3;
        }
        /// <summary>
        /// 从当前的错误报告中返回警告
        /// </summary>
        /// <param name="message"></param>
        public static void reportWarning(String message)
        {
            int[] linep = { 0 };
            String filename = getSourcePositionFromStack(linep);
            Context.reportWarning(message, filename, linep[0], null, 0);
        }

        public static void reportWarning(String message, String sourceName,
                                    int lineno, String lineSource,
                                    int lineOffset)
        {
            Context cx = Context.getContext();
            if (cx.hasFeature(FEATURE_WARNING_AS_ERROR))
                reportError(message, sourceName, lineno, lineSource, lineOffset);
            else
                cx.getErrorReporter().warning(message, sourceName, lineno,
                                              lineSource, lineOffset);
        }
        public static void reportError(String message, String sourceName,
                                   int lineno, String lineSource,
                                   int lineOffset)
        {
            Context cx = getCurrentContext();
            if (cx != null)
            {
                cx.getErrorReporter().error(message, sourceName, lineno,
                                            lineSource, lineOffset);
            }
            else
            {
                throw new EvaluatorException(message, sourceName, lineno,
                                             lineSource, lineOffset);
            }
        }

        /// <summary>
        /// 相当于调用一个上下文工厂类
        /// </summary>
        /// <returns>返回与当前线程相关联的上下文</returns>
        public static Context enter()
        {
            return enter(null);
        }
        /// <summary>
        /// 相当于调用一个上下文工厂类
        /// </summary>
        /// <param name="cx">上下文</param>
        /// <returns>返回与当前线程相关联的上下文</returns>
        public static Context enter(Context cx)
        {
            return enter(cx, ContextFactory.getGlobal());
        }

        static Context enter(Context cx, ContextFactory factory)
        {
            Object helper = VMBridge.instance.getThreadContextHelper();
            Context old = VMBridge.instance.getContext(helper);
            if (old != null)
            {
                cx = old;
            }
            else
            {
                if (cx == null)
                {
                    cx = factory.makeContext();
                    if (cx.enterCount != 0)
                    {
                        throw new Exception("返回上下文");
                    }
                    factory.onContextCreated(cx);
                    if (factory.isSealed() && !cx.isSealed())
                    {
                        cx.seal(null);
                    }
                }
                else
                {
                    if (cx.enterCount != 0)
                    {
                        throw new Exception("can not use Context instance already associated with some thread");
                    }
                }
                VMBridge.instance.setContext(helper, cx);
            }
            ++cx.enterCount;
            return cx;
        }

        public void seal(Object sealKey)
        {
            if (sealed1) onSealedMutation();
            sealed1 = true;
            this.sealKey = sealKey;
        }

        public bool isSealed()
        {
            return sealed1;
        }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="factory"></param>
        public Context(ContextFactory factory)
        {
            if (factory == null)
            {
                throw new ArgumentException("factory == null");
            }
            this.factory = factory;
            setLanguageVersion(VERSION_DEFAULT);//设置默认语言版本
            //optimizationLevel = codegenClass != null ? 0 : -1;
            optimizationLevel = -1;
            maximumInterpreterStackDepth = Int32.MaxValue;
        }
        /// <summary>
        /// 设置语言版本
        /// </summary>
        /// <param name="version"></param>
        public void setLanguageVersion(int version)
        {
            if (sealed1) onSealedMutation();
            checkLanguageVersion(version);
            Object listeners = propertyListeners;
            if (listeners != null && version != this.version)
            {//属性文件改变,不过这里就只有一种版本,所以不需要改变
                firePropertyChangeImpl(listeners, languageVersionProperty,
                                   (this.version),
                                   (version));
            }
            this.version = version;
        }

        public static void onSealedMutation()
        {
            throw new Exception();
        }

        /// <summary>
        /// 属性文件改变
        /// </summary>
        /// <param name="listeners"></param>
        /// <param name="property"></param>
        /// <param name="oldValue"></param>
        /// <param name="newValue"></param>
        private void firePropertyChangeImpl(Object listeners, String property,
                                        Object oldValue, Object newValue)
        {
            //for (int i = 0; ; ++i) {
            //    Object l = Kit.getListener(listeners, i);
            //    if (l == null)
            //        break;
            //    if (l is PropertyChangeListener) {
            //        PropertyChangeListener pcl = (PropertyChangeListener)l;
            //        pcl.propertyChange(new PropertyChangeEvent(
            //            this, property, oldValue, newValue));
            //    }
            //}

            //TODO:这里没有实现
        }

        /// <summary>
        /// 初始化标准对象
        /// </summary>
        /// <param name="scope"></param>
        /// <returns></returns>
        public Scriptable initStandardObjects(ScriptableObject scope)
        {
            return initStandardObjects(scope, false);
        }

        /// <summary>
        /// 初始化标准对象
        /// </summary>
        /// <param name="scope"></param>
        /// <param name="sealed1"></param>
        /// <returns></returns>
        public ScriptableObject initStandardObjects(ScriptableObject scope,
                                                bool sealed1)
        {
            return ScriptRuntime.initStandardObjects(this, scope, sealed1);
        }

        public Function compileFunction(Scriptable scope, String source,
                                   Evaluator compiler,
                                   ErrorReporter compilationErrorReporter,
                                   String sourceName, int lineno,
                                   Object securityDomain)
        {
            try
            {
                return (Function)compileImpl(scope, null, source, sourceName,
                                              lineno, securityDomain, true,
                                              compiler, compilationErrorReporter);
            }
            catch (IOException ioe)
            {
                // Should never happen because we just made the reader
                // from a String
                throw new Exception();
            }
        }

        public static Exception throwAsScriptRuntimeEx(Exception e)
        {
            //while ((e is Exception)) {
            //    e =  e).getTargetException();
            //}
            // special handling of Error so scripts would not catch them
            //if (e is Error) {
            //    Context cx = getContext();
            //    if (cx == null ||
            //        !cx.hasFeature(Context.FEATURE_ENHANCED_JAVA_ACCESS))
            //    {
            //        throw (Error)e;
            //    }
            //}
            //if (e instanceof RhinoException) {
            //    throw (RhinoException)e;
            //}
            //throw new WrappedException(e);
            throw e;
        }


        public static Context getContext()
        {
            Context cx = getCurrentContext();
            if (cx == null)
            {
                throw new Exception(
                    "No Context associated with current Thread");
            }
            return cx;
        }


        public WrapFactory getWrapFactory()
        {
            if (wrapFactory == null)
            {
                wrapFactory = new WrapFactory();
            }
            return wrapFactory;
        }


        public Scriptable newArray(Scriptable scope, Object[] elements)
        {
            if (elements.GetType() != typeof(Object[]))
                throw new ArgumentException();
            NativeArray result = new NativeArray(elements);
            ScriptRuntime.setObjectProtoAndParent(result, scope);
            return result;
        }

        /// <summary>
        /// 转换javascript为String
        /// See ECMA 9.8.
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static String toString(Object value)
        {
            return ScriptRuntime.toString(value);
        }

        /// <summary>
        /// 计算javascript
        /// </summary>
        /// <param name="scope">执行的域</param>
        /// <param name="source">javascript源</param>
        /// <param name="sourceName">用来描述源 例如文件名</param>
        /// <param name="lineno">起始行</param>
        /// <param name="securityDomain">安全域,可以为null</param>
        /// <returns>执行计算的结果</returns>
        public Object evaluateString(Scriptable scope, String source,
                                      String sourceName, int lineno,
                                      Object securityDomain)
        {
            Script script = compileString(source, sourceName, lineno,
                                          securityDomain);
            if (script != null)
            {
                return script.exec(this, scope);
            }
            else
            {
                return null;
            }
        }


        /// <summary>
        /// 根据字符串编译源
        /// </summary>
        /// <param name="source"></param>
        /// <param name="sourceName"></param>
        /// <param name="lineno"></param>
        /// <param name="securityDomain"></param>
        /// <returns></returns>
        public Script compileString(String source,
                                          String sourceName, int lineno,
                                          Object securityDomain)
        {
            if (lineno < 0)
            {
                lineno = 0;
            }
            return compileString(source, null, null, sourceName, lineno,
                                 securityDomain);
        }
        /// <summary>
        /// 解析中间代码
        /// </summary>
        /// <param name="source"></param>
        /// <param name="compiler"></param>
        /// <param name="compilationErrorReporter"></param>
        /// <param name="sourceName"></param>
        /// <param name="lineno"></param>
        /// <param name="securityDomain"></param>
        /// <returns></returns>
        public Script compileString(String source,
                                    Evaluator compiler,
                                    ErrorReporter compilationErrorReporter,
                                    String sourceName, int lineno,
                                    Object securityDomain)
        {
            try
            {
                return (Script)compileImpl(null, null, source, sourceName, lineno,
                                            securityDomain, false,
                                            compiler, compilationErrorReporter);
            }
            catch (IOException ex)
            {
                // Should not happen when dealing with source as string
                throw ex;
            }
        }



        private Object compileImpl(Scriptable scope,
                               StreamReader sourceReader, String sourceString,
                               String sourceName, int lineno,
                               Object securityDomain, bool returnFunction,
                               Evaluator compiler,
                               ErrorReporter compilationErrorReporter)
        {
            if (sourceName == null)
            {
                sourceName = "未命名的脚本";
            }
            if (securityDomain != null && getSecurityController() == null)
            {
                throw new ArgumentException(
                    "[安全域异常]");
            }

            // One of sourceReader or sourceString has to be null
            if (!(sourceReader == null ^ sourceString == null)) Kit.codeBug();
            // 要么加入一个域，或者做为值返回
            if (!(scope == null ^ returnFunction)) Kit.codeBug();

            CompilerEnvirons compilerEnv = new CompilerEnvirons();
            compilerEnv.initFromContext(this);
            if (compilationErrorReporter == null)
            {
                compilationErrorReporter = compilerEnv.getErrorReporter();
            }

            if (debugger != null)
            {
                if (sourceReader != null)
                {
                   // sourceString = Kit.readReader(sourceReader);
                    sourceReader = null;
                }
            }

            Parser p = new Parser(compilerEnv, compilationErrorReporter);
            if (returnFunction)
            {
                p.calledByCompileFunction = true;
            }
            ScriptOrFnNode tree;
            if (sourceString != null)
            {
                tree = p.parse(sourceString, sourceName, lineno);
            }
            else
            {
                tree = p.parse(sourceReader, sourceName, lineno);
            }
            if (returnFunction)
            {
                if (!(tree.getFunctionCount() == 1
                      && tree.getFirstChild() != null
                      && tree.getFirstChild().getType() == Token.FUNCTION))
                {
                    // XXX: the check just look for the first child
                    // and allows for more nodes after it for compatibility
                    // with sources like function() {};;;
                    throw new ArgumentException(
                        "compileFunction only accepts source with single JS function: " + sourceString);
                }
            }

            if (compiler == null)
            {
                compiler = createCompiler();
            }

            String encodedSource = p.getEncodedSource();

            Object bytecode = compiler.compile(compilerEnv,
                                               tree, encodedSource,
                                               returnFunction);

            if (debugger != null)
            {
                if (sourceString == null) Kit.codeBug();
                if (bytecode is DebuggableScript)
                {
                    DebuggableScript dscript = (DebuggableScript)bytecode;
                    notifyDebugger_r(this, dscript, sourceString);
                }
                else
                {
                    throw new Exception("NOT SUPPORTED");
                }
            }

            Object result;
            if (returnFunction)
            {
                result = compiler.createFunctionObject(this, scope, bytecode, securityDomain);
            }
            else
            {
                result = compiler.createScriptObject(bytecode, securityDomain);
            }

            return result;
        }

        private Evaluator createCompiler()
        {
            Evaluator result = null;
            if (optimizationLevel >= 0 && codegenClass != null)
            {
                //  result = (Evaluator)Kit.newInstanceOrNull(codegenClass);
                return new Interpreter();
                //  result = new Codegen();
            }
            if (result == null)
            {
                result = createInterpreter();
            }
            return result;
        }

        private static void notifyDebugger_r(Context cx, DebuggableScript dscript,
                                         String debugSource)
        {
            cx.debugger.handleCompilationDone(cx, dscript, debugSource);
            for (int i = 0; i != dscript.getFunctionCount(); ++i)
            {
                notifyDebugger_r(cx, dscript.getFunction(i), debugSource);
            }
        }
        public SecurityController getSecurityController()
        {
            SecurityController global = SecurityController.global();
            if (global != null)
            {
                return global;
            }
            return securityController;
        }
        public RegExpProxy getRegExpProxy()
        {
            if (regExpProxy == null)
            {
                Type cl = Kit.classOrNull(
                              "org.mozilla.javascript.regexp.RegExpImpl");
                if (cl != null)
                {
                    regExpProxy = (RegExpProxy)Kit.newInstanceOrNull(cl);
                }
            }
            return regExpProxy;
        }


        public static Object call(ContextFactory factory, ContextAction action)
        {
            Context cx = enter(null, factory);
            try
            {
                return action.run(cx);
            }
            finally
            {
                exit();
            }
        }

        public static void exit()
        {
            Object helper = VMBridge.instance.getThreadContextHelper();
            Context cx = VMBridge.instance.getContext(helper);
            if (cx == null)
            {
                throw new Exception(
                    "Calling Context.exit without previous Context.enter");
            }
            if (cx.enterCount < 1) Kit.codeBug();
            if (--cx.enterCount == 0)
            {
                VMBridge.instance.setContext(helper, null);
                cx.factory.onContextReleased(cx);
            }
        }

        public Scriptable newObject(Scriptable scope, String constructorName,
                                      Object[] args)
        {
            scope = ScriptableObject.getTopLevelScope(scope);
            Function ctor = ScriptRuntime.getExistingCtor(this, scope,
                                                          constructorName);
            if (args == null) { args = ScriptRuntime.emptyArgs; }
            return ctor.construct(this, scope, args);
        }

        public ClassShutter getClassShutter()
        {
            return classShutter;
        }

        public static Object javaToJS(Object value, Scriptable scope)
        {
            if (value is String || ScriptRuntime.isNumber(value)
                || value is Boolean || value is Scriptable)
            {
                return value;
            }
            else if (value is char)
            {
                return Convert.ToChar(value).ToString();
            }
            else
            {
                Context cx = Context.getContext();
                return cx.getWrapFactory().wrap(cx, scope, value, null);
            }
        }


        public void observeInstructionCount(int instructionCount)
        {
            ContextFactory f = getFactory();
            f.observeInstructionCount(this, instructionCount);
        }

        public Object[] getElements(Scriptable object1)
        {
            return ScriptRuntime.getArrayElements(object1);
        }
        /// <summary>
        /// 创建　新的javascript对象
        /// </summary>
        /// <param name="scope"></param>
        /// <returns></returns>
        public Scriptable newObject(Scriptable scope)
        {
            return newObject(scope, "Object", ScriptRuntime.emptyArgs);
        }


        /// <summary>
        /// 得到当前的　文化信息
        /// </summary>
        /// <returns></returns>
        public CultureInfo getLocale()
        {

            if (locale == null)
                locale = CultureInfo.CurrentCulture;
            return locale;
        }
        public int getMaximumInterpreterStackDepth()
        {
            return maximumInterpreterStackDepth;
        }
        public String decompileScript(Script script, int indent)
        {
            NativeFunction scriptImpl = (NativeFunction)script;
            return scriptImpl.decompile(indent, 0);
        }
        public static Object getUndefinedValue()
        {
            return Undefined.instance;
        }
        public Object evaluateReader(Scriptable scope, StreamReader reader,
                                       String sourceName, int lineno,
                                       Object securityDomain)
        {
            Script script = compileReader(scope, reader, sourceName, lineno,
                                          securityDomain);
            if (script != null)
            {
                return script.exec(this, scope);
            }
            else
            {
                return null;
            }
        }
        public Script compileReader(Scriptable scope, StreamReader reader,
                                      String sourceName, int lineno,
                                      Object securityDomain)
        {
            return compileReader(reader, sourceName, lineno, securityDomain);
        }

        public Script compileReader(StreamReader reader, String sourceName,
                                      int lineno, Object securityDomain)
      
    {
        if (lineno < 0) {
            // For compatibility IllegalArgumentException can not be thrown here
            lineno = 0;
        }
        return (Script)compileImpl(null, reader, null, sourceName, lineno,
                                    securityDomain, false, null, null);
    }

        //public XMLLib.Factory getE4xImplementationFactory()
        //{
        //    //return getFactory().getE4xImplementationFactory();
        //    return XMLLib.Factory.create(
        //        "org.mozilla.javascript.xml.impl.xmlbeans.XMLLibImpl"
        //    );
        //}

        private ClassShutter classShutter;

        private CultureInfo locale;
        public ObjToIntMap iterating;
        public RegExpProxy regExpProxy;
        private static Type codegenClass = typeof(Codegen);

        public Debugger debugger;

        public XMLLib cachedXMLLib;

        private SecurityController securityController;

        private WrapFactory wrapFactory;

        private Object sealKey;
        public bool isContinuationsTopCall;
        private int maximumInterpreterStackDepth;

        public Object interpreterSecurityDomain;
        public bool useDynamicScope;
        public int scratchIndex;
        public long scratchUint32;
        public Scriptable topCallScope;
        public static String languageVersionProperty = "language version";
        public static String errorReporterProperty = "error reporter";
        private Object propertyListeners;
        private bool sealed1;
        private int enterCount;
        public bool compileFunctionsWithDynamicScopeFlag;
        //private static Class<?> interpreterClass = Kit.classOrNull(
        //                     "org.mozilla.javascript.Interpreter");
        private ErrorReporter errorReporter;
        private bool generatingDebugChanged;
        private bool generatingDebug;
        private bool generatingSource = true;
        private int optimizationLevel;

        public bool generateObserverCount = false;//被编译后的代码的


        public Scriptable scratchScriptable;//用来返回第二个　Scriptable的结果

        public ObjArray previousInterpreterInvocations;

        public int instructionCount;
        public int instructionThreshold;
        public Object lastInterpreterFrame;
        public NativeCall currentActivationCall;
    }

}
